package com.example.appointment.service.impl;

import com.example.appointment.common.enums.RoleEnum;
import com.example.appointment.dto.LoginDTO;
import com.example.appointment.dto.RegisterDTO;
import com.example.appointment.dto.UpdatePasswordDTO;
import com.example.appointment.dto.UpdateUserDTO;
import com.example.appointment.entity.User;
import com.example.appointment.repository.UserRepository;
import com.example.appointment.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import com.example.appointment.dto.UserDTO;
import com.example.appointment.dto.UserLoginDTO;
import com.example.appointment.dto.UserRegisterDTO;
import com.example.appointment.enums.UserRole;
import com.example.appointment.utils.JwtUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.example.appointment.exception.UnauthorizedException;
import com.example.appointment.exception.BadRequestException;

import java.time.LocalDateTime;
import java.util.Optional;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final HttpServletRequest request;
    private final JwtUtils jwtUtils;

    @Override
    @Transactional
    public UserDTO register(UserRegisterDTO registerDTO) {
        // 验证用户名是否已存在
        if (userRepository.existsByUsername(registerDTO.getUsername())) {
            throw new RuntimeException("用户名已存在");
        }

        // 验证邮箱是否已存在
        if (registerDTO.getEmail() != null && userRepository.existsByEmail(registerDTO.getEmail())) {
            throw new RuntimeException("邮箱已被注册");
        }

        // 验证密码是否匹配
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new RuntimeException("两次输入的密码不一致");
        }

        // 验证角色是否有效
        try {
            UserRole.valueOf(registerDTO.getRole().toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new RuntimeException("无效的用户角色");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(registerDTO.getUsername());
        user.setPassword(registerDTO.getPassword()); // 使用明文密码
        user.setName(registerDTO.getName());
        user.setRole(registerDTO.getRole().toUpperCase());
        user.setPhone(registerDTO.getPhone());
        user.setEmail(registerDTO.getEmail());

        User savedUser = userRepository.save(user);
        return convertToDTO(savedUser);
    }

    @Override
    public UserDTO login(UserLoginDTO loginDTO) {
        // 查找用户
        User user = userRepository.findByUsername(loginDTO.getUsername())
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 验证密码（明文比较）
        if (!user.getPassword().equals(loginDTO.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 生成JWT token
        String token = jwtUtils.generateToken(user.getUsername());

        // 返回用户信息和token
        UserDTO userDTO = convertToDTO(user);
        userDTO.setToken(token);
        return userDTO;
    }

    @Override
    public void logout() {
        // JWT不需要服务端注销，客户端删除token即可
    }

    @Override
    public User getCurrentUser() {
        User user = (User) request.getAttribute("currentUser");
        if (user == null) {
            throw new RuntimeException("用户未登录");
        }
        return user;
    }

    @Override
    public UserDTO getUserByUsername(String username) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }

    @Override
    public UserDTO getCurrentUserDTO() {
        return convertToDTO(getCurrentUser());
    }

    @Override
    @Transactional
    public UserDTO updateUser(Long id, UserDTO userDTO) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));

        // 只允许更新部分字段
        user.setName(userDTO.getName());
        user.setPhone(userDTO.getPhone());
        user.setEmail(userDTO.getEmail());

        User updatedUser = userRepository.save(user);
        return convertToDTO(updatedUser);
    }

    @Override
    @Transactional
    public void deleteUser(Long id) {
        if (!userRepository.existsById(id)) {
            throw new RuntimeException("用户不存在");
        }
        userRepository.deleteById(id);
    }

    @Override
    public UserDTO getUserById(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return convertToDTO(user);
    }

    @Override
    public Page<UserDTO> getAllUsers(Pageable pageable) {
        return userRepository.findAll(pageable).map(this::convertToDTO);
    }

    @Override
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }

    @Override
    public boolean existsByEmail(String email) {
        return userRepository.existsByEmail(email);
    }

    @Override
    @Transactional
    public UserDTO updateCurrentUser(UserDTO userDTO) {
        // 获取当前登录用户
        User currentUser = getCurrentUser();
        
        // 只允许更新部分安全字段
        currentUser.setName(userDTO.getName());
        currentUser.setPhone(userDTO.getPhone());
        currentUser.setEmail(userDTO.getEmail());
        
        User updatedUser = userRepository.save(currentUser);
        return convertToDTO(updatedUser);
    }

    @Override
    public String getUserRoleById(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        return user.getRole();
    }

    @Override
    public User findUserEntityByUsername(String username) {
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }

    @Transactional
    @Override
    public void updatePassword(UpdatePasswordDTO updatePasswordDTO) {
        log.info("修改密码，开始验证");
        
        // 获取当前登录用户
        User currentUser = getCurrentUser();
        if (currentUser == null) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 验证旧密码
        if (!currentUser.getPassword().equals(updatePasswordDTO.getOldPassword())) {
            log.warn("用户密码修改失败：旧密码错误 userId={}", currentUser.getId());
            throw new BadRequestException("原密码错误");
        }
        
        // 更新密码
        currentUser.setPassword(updatePasswordDTO.getNewPassword());
        userRepository.save(currentUser);
        
        log.info("用户密码修改成功 userId={}", currentUser.getId());
    }

    private UserDTO convertToDTO(User user) {
        UserDTO dto = new UserDTO();
        dto.setId(user.getId());
        dto.setUsername(user.getUsername());
        dto.setName(user.getName());
        dto.setRole(user.getRole());
        dto.setPhone(user.getPhone());
        dto.setEmail(user.getEmail());
        dto.setCreatedAt(user.getCreatedAt());
        dto.setUpdatedAt(user.getUpdatedAt());
        return dto;
    }
} 